#!/usr/bin/python

# CS380 Assignment 2
# String Generator

import sys
import random
import time
import math
import string
import bnfBlock
from cgiClass import *

MAX = 1024
global MAX 

class strGen:
	def __init__(self, fileNameIn, seedIn, verboseIn):
		# Pre:	take in the name of the bnf file
		# Post:	internalize the bnf file into our data structure
		#self.bnfList = []
		self.verbose = verboseIn
		self.parseLines(open(fileNameIn, 'r').readlines())
		self.initialize()

	def __init__(self, bnfList):
		# Pre:	take in a list of bnf lines
		# Post:	internalize those lines
		self.parseLines(bnfList)
		self.initialize()

	def initialize(self): 
		# Pre:	none
		# Post:	do some house keeping common to both of the 
		#			constructors
		#self.bnfList = []
		self.parseSteps = []
		self.doneParsing = 0
		self.verbose = 0
		self.inString = "<S>"
		while not self.doneParsing:
			self.parseString(self.inString)
		self.showHTML()

	def showHTML(self):
		print "<html><head><title>BNF Results</title></head>"
		print "<body bgcolor='white' link='darkblue'><font face='Arial'>"
		print "<table border=0 width=100%>"
		print "<tr bgcolor='#DDDDDD'><td><font face='Arial'>"
		print "<h2>Output string: <u>%s</u></h2>" % (self.outString)
		print "</font></td></tr></table>" 

		# show the input string
		print "<table width=100%><tr><td valign='top'><font face='Arial'>BNF Input</font></td><td>"
		print "<table width=100% border=0 cellspacing=0 cellpadding=0>"
		aColor = "#AAAAAA"
		bColor = "#DDDDDD"
		altLine = -1
		for line in self.bnfRec[:-1]:
			altLine = altLine * (-1)
			currColor = bColor
			if altLine < 0: currColor = aColor
			print "<tr bgcolor='%s'>" % (currColor)
			for cell in line:
				#print "<td><font face='Arial'>", self.printNorm('%s' % cell), "</td>" 
				print "<td><font face='Arial'>%s</td>" % (self.normalize('%s' % cell)) 
			print "</tr>"
		print "</table>"
		print "</td></tr></table>"
		
		# show the steps of the output
		#self.parseSteps
		print "<table width=100%><tr><td valign='top'><font face='Arial'>Parsing Steps</font></td><td>"
		print "<table width=100% border=0 cellspacing=0 cellpadding=0>"
		aColor = "#AAAAAA"
		bColor = "#DDDDDD"
		altLine = -1
		for line in self.parseSteps:
			altLine = altLine * (-1)
			currColor = bColor
			if altLine < 0: currColor = aColor
			print "<tr bgcolor='%s'>" % (currColor)
			for cell in line:
				#print "<td><font face='Arial'>", self.printNorm('%s' % cell), "</td>" 
				print "<td><font face='Arial'>%s</td>" % (self.normalize('%s' % cell)) 
			print "</tr>"
		print "</table>"
		print "</td></tr></table>"

		print "<table border=0>"
		print "<tr bgcolor='#DDDDDD'><td><font face='Arial'>"
		print "<i>This document is output from the BNF Parser/ String Generator"
		print "written by <a href='http://www.ophinity.com'>"
		print "Demian L. Neidetcher</a>.  This was implemented in the Python programming"
		print "language</i>"
		print "<br>"
		print "Source Code:"
		print "<ul>"
		print "<li><a href='strGen.cgi~'>strGen.cgi</a>"
		print "<li><a href='cgiClass.py~'>cgiClass.py</a>"
		print "<li><a href='bnfBlock.py~'>bnfBlock.py</a>"
		print "</ul>"
		print "</font></td></tr></table>" 
		print "</font></body></html>"

	def __repr__(self):
		#return "%s->%s" % (self.inString, self.outString)
		return "%s" % (self.outString)

	def parseLines(self, listIn):
		# Pre:	take in a list of lines from a bnf file
		# Post:	parse the lines and internalize the semantics
		self.bnfList = []
		lineNum = 0 
		self.bnfRec = []
		for line in listIn:
			bnfLine = []
			lineNum = lineNum + 1
			bnfLine.append(lineNum)

			currBnf = bnfBlock.bnfBlock(line)
			#print self.printNorm('%s' % currBnf)

			self.bnfList.append(currBnf)
			bnfLine.append(line)
			self.bnfRec.append(bnfLine)

	def parseString(self, stringIn):
		# Pre:	take in a string
		# Post:	apply rules to generate new string
		self.parseSteps.append([stringIn])	
		if self.verbose: 
			outStr = "current string: %s\n" % (stringIn)
			print outStr

		if len(stringIn) >= MAX: 	
			return self.inString

		ntBegin = string.find(stringIn, '<')
		if ntBegin == -1:
			self.doneParsing = 1
			self.outString = stringIn
			return stringIn

		ntEnd = string.find(stringIn, '>') + 1
		nTerm = stringIn[ntBegin:ntEnd]
		newStr = self.applyRule(nTerm)
		new = "%s%s%s" % (stringIn[:ntBegin], newStr, stringIn[ntEnd:])
		self.parseString(new)

	def applyRule(self, charIn):
		# Pre:	takes in a character
		# Post:	returns string after applying rules
		for rule in self.bnfList:
			#print "rule: %s" % self.normalize('%s' % (rule))
			if rule.getName() == charIn:
				return rule.getTrans()

	def printNorm(self, strIn):
		# Pre:	takes in a string
		# Post:	prints out the string after normalization
		print self.normalize(strIn)

	def normalize(self, strIn):
		# Pre:	takes in a string
		# Post:	replace all the <> with &gt; &lt;
		return string.replace(string.replace(strIn, '<', '&lt;'), '>', '&gt;')

	def isDone(self, stringIn):
		# Pre:	takes in a string
		# Post:	return true if the string is all lowercase
		if string.find(stringIn, '<') == -1:
			return true
		return false

if __name__=="__main__":
	#if len(sys.argv) ==  1: 
	#	form = cgiClass()
	#	bnfData = string.split(form.get('bnf'), "\n")
	#	st = strGen(bnfData)
	#else:
	#	bnfFile = "fCookie.bnf"
	#	seed = 1 
	#	verbose = 0

	#	if len(sys.argv) > 1: bnfFile = sys.argv[1]
	#	if len(sys.argv) > 2: seed = sys.argv[2]
	#	if len(sys.argv) > 3: verbose = sys.argv[3]

	#	st = strGen(bnfFile, seed, verbose)
	#	print st

	#st = strGen('fCookie.bnf', 1, 1)
	form = cgiClass()
	st = strGen(open('meetingBs.bnf', 'r').readlines())
	print st



